package com.ly.mpayment.core.util;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.google.gson.Gson;
import com.ly.mpayment.persist.common.CustomUUID;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.CycleDetectionStrategy;
import net.sf.json.util.PropertyFilter;

/**
 * JSon工具
 *
 *
 */
public class JsonUtils implements PropertyFilter {

	/**
	 * <p>
	 * 将对象转成json字符串，采用gson作为转为支持 日期类型默认转为毫秒数
	 * </p>
	 *
	 * @param obj
	 *            需要转json的实体对象
	 * @return
	 */
	public static String convertObjectToJson(Object obj) {
		Gson gson = GSONFactory.getGson();
		return gson.toJson(obj);
	}

	public static JSONObject getJSONOBJCT(){
		return new JSONObject();
	}

	public static JSONArray getJSONARRAY(){
		return new JSONArray();
	}

	public static JSONObject converToJson(String data){
//		return GSONFactory.getGson().fromJson(data, JSONObject.class);
		return JSONObject.fromObject(data);
	}


	/**
	 * <p>
	 * 将对象转成json字符串，可通过excludeProperties忽略不需要转换的属性 日期类型默认转为“YYYY-MM-dd”的格式
	 * </p>
	 *
	 * @param obj
	 *            需要转json的对象实体
	 * @param excludeProperties
	 *            需要忽略的属性数组
	 * @return
	 */
	public static String convertObjectToJson(Object obj, String[] excludeProperties) {
		return JSONObject.fromObject(obj, getJsonConfig(excludeProperties)).toString();
	}

	/**
	 * 遍历元素
	 *
	 * @param node
	 *            元素
	 * @param json
	 *            将元素遍历完成之后放的JSON对象
	 */
	@SuppressWarnings("unchecked")
	public static void iterateNodes(Element node, JSONObject json) {
		// 获取当前元素的名称
		String nodeName = node.getName();
		// 判断已遍历的JSON中是否已经有了该元素的名称
		if (json.containsKey(nodeName)) {
			// 该元素在同级下有多个
			Object Object = json.get(nodeName);
			JSONArray array = null;
			if (Object instanceof JSONArray) {
				array = (JSONArray) Object;
			} else {
				array = new JSONArray();
				array.add(Object);
			}
			// 获取该元素下所有子元素
			List<Element> listElement = node.elements();
			if (listElement.isEmpty()) {
				// 该元素无子元素，获取元素的值
				String nodeValue = node.getTextTrim();
				array.add(nodeValue);
				json.put(nodeName, array);
				return;
			}
			// 有子元素
			JSONObject newJson = new JSONObject();
			// 遍历所有子元素
			for (Element e : listElement) {
				// 递归
				iterateNodes(e, newJson);
			}
			array.add(newJson);
			json.put(nodeName, array);
			return;
		}
		// 该元素同级下第一次遍历
		// 获取该元素下所有子元素
		List<Element> listElement = node.elements();
		if (listElement.isEmpty()) {
			// 该元素无子元素，获取元素的值
			String nodeValue = node.getTextTrim();
			json.put(nodeName, nodeValue);
			return;
		}
		// 有子节点，新建一个JSONObject来存储该节点下子节点的值
		JSONObject object = new JSONObject();
		// 遍历所有一级子节点
		for (Element e : listElement) {
			// 递归
			iterateNodes(e, object);
		}
		json.put(nodeName, object);
		return;
	}


	/**
	 * <p>
	 * 将List集合转成json字符串，可通过excludeProperties忽略不需要转换的属性 日期类型默认转为“YYYY-MM-dd”的格式
	 * </p>
	 *
	 * @Date 2013-7-10 上午11:12:14
	 * @param obj
	 *            需要转json的对象实体
	 * @param excludeProperties
	 *            需要忽略的属性数组
	 * @return
	 */
	public static String convertListToJson(Object obj, String[] excludeProperties) {

		return JSONArray.fromObject(obj, getJsonConfig(excludeProperties)).toString();
	}

	/**
	 * <p>
	 * JSON过滤
	 * </P>
	 *
	 * @Date 2013-7-10 下午12:21:29
	 * @param excludeProperties
	 *            需要忽略的属性数组
	 * @return
	 */
	private static JsonConfig getJsonConfig(String[] excludeProperties) {
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.registerJsonValueProcessor(CustomUUID.class, new CustomJsonValueProcessor());
		jsonConfig.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {
			public Object processArrayValue(Object value, JsonConfig jsonConfig) {
				if (value instanceof Date && value != null)
					return DateUtils.convert((Date) value, DateUtils.YYYY_MM_DD);
				return null;
			}

			public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
				if (value instanceof Date && value != null) {
					return DateUtils.convert((Date) value, DateUtils.YYYY_MM_DD);
				}
				return null;
			}
		});
		if (excludeProperties != null)
			jsonConfig.setExcludes(excludeProperties);
		return jsonConfig;
	}

	// Log log = LogFactory.getLog(this.getClass());

	/**
	 * 忽略的属性名称
	 */
	private String[] fields;

	/**
	 * 是否忽略集合
	 */
	private boolean ignoreColl = false;

	/**
	 * 空参构造方法<br/>
	 * 默认不忽略集合
	 */
	public JsonUtils() {
		// empty
	}

	/**
	 * 构造方法
	 *
	 * @param fields
	 *            忽略属性名称数组
	 */
	public JsonUtils(String[] fields) {
		this.fields = fields;
	}

	/**
	 * 构造方法
	 *
	 * @param ignoreColl
	 *            是否忽略集合
	 * @param fields
	 *            忽略属性名称数组
	 */
	public JsonUtils(boolean ignoreColl, String[] fields) {
		this.fields = fields;
		this.ignoreColl = ignoreColl;
	}

	/**
	 * 构造方法
	 *
	 * @param ignoreColl
	 *            是否忽略集合
	 */
	public JsonUtils(boolean ignoreColl) {
		this.ignoreColl = ignoreColl;
	}

	public boolean apply(Object source, String name, Object value) {
		Field declaredField = null;
		// 忽略值为null的属性
		if (value == null)
			return true;
		// 剔除自定义属性，获取属性声明类型
		if (!"data".equals(name) && "data" != name && !"totalSize".equals(name) && "totalSize" != name) {
			try {
				declaredField = source.getClass().getDeclaredField(name);
			} catch (NoSuchFieldException e) {
				// log.equals("没有找到属性" + name);
				e.printStackTrace();
			}
		}
		// 忽略集合
		if (declaredField != null) {
			if (ignoreColl) {
				if (declaredField.getType() == Collection.class || declaredField.getType() == Set.class) {
					return true;
				}
			}
		}

		// 忽略设定的属性
		if (fields != null && fields.length > 0) {
			if (juge(fields, name)) {
				return true;
			} else {
				return false;
			}
		}

		return false;
	}

	/**
	 * 过滤忽略的属性
	 *
	 * @param s
	 * @param s2
	 * @return
	 */
	public boolean juge(String[] s, String s2) {
		boolean b = false;
		for (String sl : s) {
			if (s2.equals(sl)) {
				b = true;
			}
		}
		return b;
	}

	public String[] getFields() {
		return fields;
	}

	/**
	 * 设置忽略的属性
	 *
	 * @param fields
	 */
	public void setFields(String[] fields) {
		this.fields = fields;
	}

	public boolean isIgnoreColl() {
		return ignoreColl;
	}

	/**
	 * 设置是否忽略集合类
	 *
	 * @param ignoreColl
	 */
	public void setIgnoreColl(boolean ignoreColl) {
		this.ignoreColl = ignoreColl;
	}

	// 过滤属性
	@SuppressWarnings("static-access")
	public static String excludes(Object object, String[] str) {
		JSONObject ojb = new JSONObject();
		JsonConfig config = new JsonConfig();
		config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		config.setIgnoreTransientFields(true);
		String s[] = new String[] { "totalPages", "prePage", "nextPage", "hasPre", "hasNext", "first", "orderBySetted",
				"order", "autoCount"};
		config.setExcludes(concat(s,str));
		config.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		config.registerJsonValueProcessor(BigDecimal.class, new JsonDateValueProcessor());
		// config.setJsonPropertyFilter(new IgnoreFieldProcessorImpl(true,
		// str)); // 忽略掉name属性及集合对象
		if (object == null) {
			return ojb.toString();
		}
		return ojb.fromObject(object, config).toString();
	}

	/**
	 * 对象转json字符
	 *
	 * @param object
	 * @return
	 */
	public static String objToJsonString(Object object) {
		return JSONObject.fromObject(object).toString();
	}

	/**
	 * 数组转json字符
	 *
	 * @param object
	 * @return
	 */
	public static String JSONARRAYToJsonString(Object object) {
		JSONObject ojb = new JSONObject();
		JsonConfig config = new JsonConfig();
		config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		config.setIgnoreTransientFields(true);
		config.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		// config.setJsonPropertyFilter(new IgnoreFieldProcessorImpl(true,
		// str)); // 忽略掉name属性及集合对象
		if (object == null) {
			return ojb.toString();
		}
		return new JSONArray().fromObject(object, config).toString();
	}

	/**
	 * 对象转json对象
	 *
	 * @param object
	 * @return
	 */
	public static JSONObject objToJson(Object object) {
		return new JSONObject().fromObject(object);
	}

	/**
	 * 对象转json对象
	 *
	 * @param object
	 * @return
	 */
	@SuppressWarnings("unused")
	public static String jsonArrayToJson(Object object, String[] str) {
		if (object == null) {
			return new JSONArray().toString();
		}
		JsonConfig config = new JsonConfig();
		config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		config.setIgnoreTransientFields(true);
		String s[] = new String[] { "totalPages", "prePage", "nextPage", "hasPre", "hasNext", "first", "orderBySetted",
				"order", "autoCount"};
		config.setExcludes(concat(s,str));
		config.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		if (object == null) {
			return new JSONArray().toString();
		}
		return new JSONArray().fromObject(object, config).toString();
	}

	static String[] concat(String[] a, String[] b) {
		String[] c = new String[a.length + b.length];
		System.arraycopy(a, 0, c, 0, a.length);
		System.arraycopy(b, 0, c, a.length, b.length);
		return c;
	}

	/**
	 * 对象转json对象
	 *
	 * @param object
	 * @return
	 */
	public static JSONArray jsonArrayStringToJsonArray(Object object) {
		JsonConfig config = new JsonConfig();
		config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		config.setIgnoreTransientFields(true);
		// config.setExcludes(str);
		config.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		return JSONArray.fromObject(object);
	}

	public static String xmlParseToJson(String result){
		JSONObject json = JsonUtils.getJSONOBJCT();
		Document document = null;
		try {
			document = DocumentHelper.parseText(result);
			Element rootElement = document.getRootElement();
			for (Iterator<?> iterator = rootElement.elementIterator(); iterator.hasNext();) {
				Element element = (Element) iterator.next();
				if(element.getName().equals("data")){
					List<Element> list = element.elements();
					for(Element ele : list){
						json.put(ele.getName(),ele.getData());
					}
				}else{
					json.put(element.getName(),element.getData());
				}
			}
			return json.toString();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) {
		// JsonConfig config = new JsonConfig();
		// config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		// config.setExcludes(str);
		// config.setJsonPropertyFilter(new IgnoreFieldProcessorImpl(true, new
		// String[] { "name" })); // 忽略掉name属性及集合对象

		// Entity entity = new Entity();
		// entity.setAddress("xxxxxxx");
		// entity.setAge(20);
		// entity.setName("lxb");
		// JSONObject fromObject = JSONObject.fromObject(entity, config );
		// System.out.print(fromObject.toString());
		// JSONIgnoreField.objToJson(object)
	}


}

/**
 * 日期处理类 默认为 yyyy-MM-dd HH:mm:ss
 *
 */
class JsonDateValueProcessor implements JsonValueProcessor {
	private String format = "yyyy-MM-dd HH:mm:ss";

	public JsonDateValueProcessor() {
		super();
	}

	public JsonDateValueProcessor(String format) {
		super();
		this.format = format;
	}

	public Object processArrayValue(Object paramObject, JsonConfig paramJsonConfig) {
		return process(paramObject);
	}

	public Object processObjectValue(String paramString, Object paramObject, JsonConfig paramJsonConfig) {
		return process(paramObject);
	}

	private Object process(Object value) {
		if (value instanceof Date) {
			SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.CHINA);
			return sdf.format(value);
		}
		if (value instanceof BigDecimal) {
			return value.toString();
		}
		return value == null ? "" : value.toString();
	}


}
